﻿using Asp.Versioning;
using FlyingEye.ControllerServices;
using FlyingEye.Exceptions;
using FlyingEye.Monitors.Models;
using FlyingEye.Monitors.Repositories;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace FlyingEye.Controllers
{
    [Authorize]
    [ControllerName("DeviceClient")]
    [ApiVersion("1.0")]
    [Route("api/device-monitor-service/v{version:apiVersion}/device-clients")]
    public class DeviceClientController : DefaultController
    {
        private readonly IDeviceClientRepository _deviceClientRepository;

        private readonly IReadNumericValueTaskRepository _readNumericValueTaskRepository;

        private readonly IReadStringValueTaskRepository _readStringValueTaskRepository;

        public DeviceClientController(
            IDeviceClientRepository deviceClientRepository,
            IReadNumericValueTaskRepository readNumericValueTaskRepository,
            IReadStringValueTaskRepository readStringValueTaskRepository)
        {
            _deviceClientRepository = deviceClientRepository;
            _readNumericValueTaskRepository = readNumericValueTaskRepository;
            _readStringValueTaskRepository = readStringValueTaskRepository;
        }

        [HttpGet("{id}/read-numeric-value-tasks", Name = "GetReadNumericValueTaskByDeviceClientId")]
        public async Task<ActionResult<List<ReadNumericValueTaskResponse>>> GetReadNumericValueTaskAsync(Guid id)
        {
            return await this.GetInvokeAsync(async () =>
            {
                var list = await _readNumericValueTaskRepository.GetListAsync(item => item.DeviceClientId == id);
                return ObjectMapper.Map<List<ReadNumericValueTaskModel>, List<ReadNumericValueTaskResponse>>(list);
            });
        }

        [HttpGet("{id}/read-string-value-tasks", Name = "GetReadStringValueTaskByDeviceClientId")]
        public async Task<ActionResult<List<ReadStringValueTaskResponse>>> GetReadStringValueTaskAsync(Guid id)
        {
            return await this.GetInvokeAsync(async () =>
            {
                var list = await _readStringValueTaskRepository.GetListAsync(item => item.DeviceClientId == id);
                return ObjectMapper.Map<List<ReadStringValueTaskModel>, List<ReadStringValueTaskResponse>>(list);
            });
        }

        [HttpGet("{id}", Name = "GetByDeviceClientId")]
        public async Task<ActionResult<DeviceClientResponse>> GetAsync(Guid id)
        {
            return await this.GetInvokeAsync(async () =>
            {
                var model = await _deviceClientRepository.GetAsync(id);

                return ObjectMapper.Map<DeviceClientModel, DeviceClientResponse>(model);
            });
        }

        [HttpGet]
        public async Task<ActionResult<List<DeviceClientResponse>>> GetListAsync()
        {
            return await this.GetInvokeAsync(async () =>
            {
                var list = await _deviceClientRepository.GetListAsync();
                return ObjectMapper.Map<List<DeviceClientModel>, List<DeviceClientResponse>>(list);
            });
        }

        [HttpPost]
        public async Task<ActionResult<DeviceClientResponse>> InsertAsync([FromBody] CreateDeviceClientRequest request)
        {
            if (string.IsNullOrWhiteSpace(request.ProcessName))
            {
                throw new AppArgumentValidationException("工序名称不能为空");
            }
            if (string.IsNullOrWhiteSpace(request.ResourceId))
            {
                throw new AppArgumentValidationException("设备资源 ID 不能为空");
            }
            if (request.Site <= 0)
            {
                throw new AppArgumentValidationException("站点必须大于 0");
            }

            return await this.InsertInvokeAsync(async () =>
            {
                var model = ObjectMapper.Map<CreateDeviceClientRequest, DeviceClientModel>(request);
                var result = await _deviceClientRepository.InsertAsync(model);
                return ObjectMapper.Map<DeviceClientModel, DeviceClientResponse>(result);
            }, "GetByDeviceClientId", result => new { id = result.Id });
        }

        [HttpPut]
        public async Task<ActionResult<DeviceClientResponse>> UpdateAsync([FromBody] UpdateDeviceClientRequest request)
        {
            if (request.Id == Guid.Empty)
            {
                throw new AppArgumentValidationException("Id 不能为空");
            }
            if (string.IsNullOrWhiteSpace(request.ProcessName))
            {
                throw new AppArgumentValidationException("工序名称不能为空");
            }
            if (string.IsNullOrWhiteSpace(request.ResourceId))
            {
                throw new AppArgumentValidationException("设备资源 ID 不能为空");
            }
            if (request.Site <= 0)
            {
                throw new AppArgumentValidationException("站点必须大于 0");
            }

            return await this.PutInvokeAsync(async () =>
            {
                var model = ObjectMapper.Map<UpdateDeviceClientRequest, DeviceClientModel>(request);
                var result = await _deviceClientRepository.UpdateAsync(model);
                return ObjectMapper.Map<DeviceClientModel, DeviceClientResponse>(result);
            });
        }

        [HttpDelete("{id}")]
        public Task<NoContentResult> DeleteAsync(Guid id)
        {
            return this.DeleteInvokeAsync(async () =>
            {
                await _deviceClientRepository.DeleteAsync(id);
            });
        }
    }
}
